package com.alan.sso.server.controller;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import com.alan.sso.server.bean.AppConfig;
import com.alan.sso.server.bean.User;
import com.alan.sso.server.service.ILoginServer;
import com.alan.sso.share.bean.Constant;
import com.alan.sso.share.bean.SsoConfigData;
import com.alan.sso.share.bean.SsoUser;
import com.alan.sso.share.utils.SsoCookieUtils;
import com.alan.sso.share.utils.URIBuilder;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * @Auther: Alan liu
 * @Date: 2018/12/20 16:58
 * @Description: SsoLoginController
 */
@Slf4j
@Controller
@RequestMapping("sso")
public class SsoLoginController {

    @Value("${sso.key}")
    private String key;

    @Value("${sso.url}")
    private String ssoUrl;

    @Autowired
    ILoginServer loginServer;

    /**
     * @Author Alan liu
     * @Description 检查是否登录，如未登录到登录页面，已登录就跳过登录流程。
     * @Date 13:28 2018/12/21
     * @param request
     * @param response
     * @return java.lang.String
     **/
    @RequestMapping(value = "login",method = RequestMethod.GET)
    public String login(HttpServletRequest request, HttpServletResponse response, Model model){
        String ticket = request.getParameter(Constant.K_TICKET);
        String appName = request.getParameter(Constant.K_APPNAME);
        String target = request.getParameter(Constant.K_TARGET);
        try {
            target = URLDecoder.decode(target,"UTF-8");
            // 如有ticket检查是否是有效，如是有效的则返回原地址并带上ticket
            if(StringUtils.isNotEmpty(ticket)){
                if(loginServer.checkTicket(ticket)){
                    String url = new URIBuilder(target).addParameter(Constant.K_TICKET,ticket).toString();
                    response.sendRedirect(url);
                    return null;
                }
            }
        }catch (Exception e){
            log.error("异常：{}",e);
        }
        model.addAttribute(Constant.K_TARGET,target);
        model.addAttribute(Constant.K_APPNAME,appName);
        // 如ticket无效或没有，则到登录页面进行登录
        return "/html/login";
    }

    /**
     * @Author Alan liu
     * @Description 用户登录验证(简易处理)
     * @Date 13:28 2018/12/21
     * @param request
     * @param response
     * @return java.lang.String
     **/
    @RequestMapping(value = "login",method = RequestMethod.POST)
    public String loginPost(HttpServletRequest request, HttpServletResponse response, String username, String password ){
        //取用户密码，进行验证
        String targetT = request.getParameter(Constant.K_TARGET);
        try {
            String target = URLDecoder.decode(targetT,"UTF-8");
            String appName = request.getParameter(Constant.K_APPNAME);
            AppConfig appConfig = loginServer.getAppConfig(appName);
            User user = loginServer.getUserByUserName(username);
            String msg = "";
            if(user==null){
                msg = "用户不存在!";
                log.info("用户不存在!");
            }
            if(user.getPassword().equals(password)){
                String ticket = loginServer.generateTicket(user);
                String url = new URIBuilder(target).addParameter(Constant.K_TICKET,ticket).toString();
                if(appConfig!=null){
                    String ssoAppName = SecureUtil.aes(key.getBytes()).encryptBase64(appName);
                    Cookie cookie = new Cookie(Constant.K_SSO_CASTGC, ssoAppName);
                    cookie.setPath("/sso");
                    cookie.setDomain("sso.alan.com");
                    //1天
                    cookie.setMaxAge(3600*24);
                    response.addCookie(cookie);
//                    response.sendRedirect(url);
//                    return null;
                    //跳回来源地，并设置cookie。
                    return "redirect:"+url;
                }
            }else {
                msg = "用户密码不对！";
                log.info("用户密码不对！");
            }
        } catch (Exception e) {
            log.error("异常：{}",e);
        }
        return "/html/login";
    }

    /**
     * @Author Alan liu
     * @Description 验证ticket，返回用户json信息
     * @Date 13:30 2018/12/21
     * @param
     * @return java.lang.String
     **/
    @RequestMapping(value = "validate",method = RequestMethod.GET)
    @ResponseBody
    public SsoUser validate(HttpServletRequest request, HttpServletResponse response){
        String ticket = request.getParameter(Constant.K_TICKET);
        SsoUser ssoUser = new SsoUser();
        if(loginServer.checkTicket(ticket)){
            ssoUser = loginServer.getSsoUserByTicket(ticket);
        }
        return ssoUser;
    }


    /**
     * @Author Alan liu
     * @Description 退出登录
     * @Date 13:31 2018/12/21
     * @param
     * @return java.lang.String
     **/
    @RequestMapping(value = "logout",method = RequestMethod.GET)
    public String logout(HttpServletRequest request, HttpServletResponse response){
        String target = request.getParameter(Constant.K_TARGET);
        //解密appName
        String ssoCastgc = SsoCookieUtils.getCookie(request,Constant.K_SSO_CASTGC).getValue();
        //初始化aes
        AES aes = SecureUtil.aes( key.getBytes());
        String appName = aes.decryptStrFromBase64(ssoCastgc);
        AppConfig appConfig = loginServer.getAppConfig(appName);
        String encryptedSession = SsoCookieUtils.getCookie(request,Constant.K_SESSION_KEY).getValue();
        String sessionCookieJson = SecureUtil.aes(appConfig.getAppKey().getBytes()).decryptStrFromBase64(encryptedSession);
        SsoUser ssoUser = JSON.parseObject(sessionCookieJson,SsoUser.class);
        loginServer.logout(ssoUser);
        if(StringUtils.isNotEmpty(target)){
            return "redirect:"+target;
        }
        return "/html/logout";
    }


}
